package com.zr.planclass.service.impl;

import com.zr.enumvo.StatusEnum;
import com.zr.planclass.mapper.PlanClassMapper;
import com.zr.planclass.model.*;
import com.zr.planclass.service.PlanClassService;
import com.zr.planclass.util.AllRecords;
import com.zr.planclass.util.ResultBuilderVo;
import com.zr.planclass.util.ResultVo;
import com.zr.util.ErrorMessageClass;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.omg.CORBA.portable.InputStream;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;

/**
 * Created by Lenovo on 2019/12/22.
 */
@Service
public class PlanClassServiceImpl implements PlanClassService {
    @Autowired
    private PlanClassMapper planClassMapper;

    @Override
    @Transactional
    public ResultVo addPlanClass(@Valid List<PlanClassAddVo> planClassAddVo) {
        //验证计划大类编码不能重复
        /*int countCode = planClassMapper.queryByCode(planClassAddVo.getCode());
        if (countCode > 0) {
            return ResultBuilderVo.error("计划大类编码已经存在!");
        }
        //验证名称
        ResultVo resultVo = vlidate(planClassAddVo.getName());
        if (!resultVo.getSuccess()) {
            return resultVo;
        }*/
        //给创建人员，时间等赋值
        PlanClassVo planClassVo = new PlanClassVo();
        //BeanUtils.copyProperties 可以把左边实体类的字段赋值给右边实体类的字段
        //注意：字段名必须一致才能赋值
        //注意：如果存在集合类型 集合类型必须一致，集合名称也必须一致
        BeanUtils.copyProperties(planClassAddVo, planClassVo);
        Date nowDate = new Date();
        planClassVo.setCreateName("小明");
        planClassVo.setCreateTime(nowDate);
        planClassVo.setUpdateName("小明");
        planClassVo.setUpdateTime(nowDate);
        //入库
        //planClassMapper.add(planClassVo);
        return ResultBuilderVo.success();
    }

    @Override
    @Transactional
    public ResultVo updatePlanClass(@Valid PlanClassUpdateVo planClassUpdateVo) {
        //验证修改的数据是否存在
        PlanClassVo planClassVo = planClassMapper.queryById(planClassUpdateVo.getId());
        if (planClassVo == null) {
            return ResultBuilderVo.error("修改数据不存在!");
        }
        if (!planClassVo.getStatus()) {
            return ResultBuilderVo.error(StatusEnum.jinyong.getName());
        }
        if (planClassVo.getStatus()) {
            return ResultBuilderVo.error(StatusEnum.qiyong.getName());
        }
        //验证名称
        ResultVo resultVo = vlidate(planClassUpdateVo.getName());
        if (!resultVo.getSuccess()) {
            return resultVo;
        }
        //赋值updateName updateTime赋值
        PlanClassVo planClass = new PlanClassVo();
        //BeanUtils.copyProperties 可以把左边实体类的字段赋值给右边实体类的字段
        //注意：字段名必须一致才能赋值
        //注意：如果存在集合类型 集合类型必须一致，集合名称也必须一致
        BeanUtils.copyProperties(planClassUpdateVo, planClass);
        Date nowDate = new Date();
        planClassVo.setUpdateName("小明");
        planClassVo.setUpdateTime(nowDate);
        planClassMapper.update(planClass);
        return ResultBuilderVo.success();
    }

    @Override
    public ResultVo see(Integer id) {
        PlanClassVo planClassVo = planClassMapper.queryById(id);
        if (planClassVo == null) {
            return ResultBuilderVo.error("操作对象不存在");
        }
        return ResultBuilderVo.success(planClassVo);
    }

    @Override
    @Transactional
    public ResultVo updateStatus(@Valid PlanClassUpdateStatusVo planClassUpdateStatusVo) {
        PlanClassVo planClassVo = planClassMapper.queryById(planClassUpdateStatusVo.getId());
        if (planClassVo == null) {
            return ResultBuilderVo.error("操作对象不存在");
        }
        PlanClassVo planClassVo1 = new PlanClassVo();
        BeanUtils.copyProperties(planClassUpdateStatusVo, planClassVo1);
        Date nowDate = new Date();
        planClassVo.setUpdateName("小明");
        planClassVo.setUpdateTime(nowDate);
        planClassMapper.updateStatus(planClassVo1);
        return ResultBuilderVo.success();
    }

    @Override
    public ResultVo queryPage(PlanClassSelectVo planClassSelectVo) {
        AllRecords allRecords = new AllRecords();
        //根据条件查询总条数
        int count = planClassMapper.queryCount(planClassSelectVo);
        //根据条件查询数据
        List<PlanClassVo> planClassVoList = planClassMapper.queryData(planClassSelectVo);
        for (PlanClassVo planClassVo : planClassVoList) {
            if (planClassVo.getStatus() != null) {
                if (!planClassVo.getStatus()) {
                    planClassVo.setStatusName("禁用");
                } else {
                    planClassVo.setStatusName("启用");
                }
            }

        }
        allRecords.setPageIndex(planClassSelectVo.getPageIndex());
        allRecords.setPageSize(planClassSelectVo.getPageSize());
        allRecords.setTotalNumber(count);
        allRecords.setDataList(planClassVoList);
        allRecords.resetTotalNumber(count);
        return ResultBuilderVo.success(allRecords);
    }

    //验证名称不能重复
    private ResultVo vlidate(String name) {
        int countName = planClassMapper.queryByName(name);
        if (countName > 0) {
            return ResultBuilderVo.error(ErrorMessageClass.PLANCLASSADDNAME);
        }
        return ResultBuilderVo.success();
    }
    /*导入*/
    @Override
    public ResultVo importPlanClass(MultipartFile file) throws Exception{
         //  1.给用户提供导入模板
        //  2.提示版本问题，询问产品经理支持哪种版本的导入格式，使用2007版本的导入模板，根据版本不同，poi导入技术的读取方式不同
        if (!file.getOriginalFilename().contains("xlsx")){
            return ResultBuilderVo.error("文件必须是2007版本！");
        }
        // 3.模板是否是需要导入的模板，验证模板是否正确
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取单元格中的信息 at0是获取sheet1中的数据。
        XSSFSheet sheet = workbook.getSheetAt(0);
        System.out.println(sheet.getRow(sheet.getFirstRowNum()).getCell(0));
        //验证第一列第一行的表格标头信息是否为 “询价单导入”，如果不是，提示模板错误。
        if (!String.valueOf(sheet.getRow(sheet.getFirstRowNum()).getCell(0)).equals("计划大类导入模板")) {
            return ResultBuilderVo.error("模板错误，请检查模板！");
        }
        List<PlanClassAddVo> planClassVoList = new ArrayList<>();
        //遍历excel表格中的所有数据，从第五行开始读取，没有数据时终止遍历。
        for (int i = sheet.getFirstRowNum() + 6; i <= sheet.getLastRowNum(); i++) {
            //读取每一行的数据
            XSSFRow xssfRow = sheet.getRow(i);
            if(xssfRow!=null) {

                String test1 = String.valueOf(xssfRow.getCell(1)).trim();
                String test2 = String.valueOf(xssfRow.getCell(2)).trim();
                String test3 = String.valueOf(xssfRow.getCell(3)).trim();
                if (!test1.equals("")&&!test1.equals("null")
                        ||!test2.equals("")&&!test2.equals("null")
                        ||!test3.equals("")&&!test3.equals("null")){
                    //把每一行的数据放入到实体类中
                    ResultVo<PlanClassAddVo> inquiryImportVo = build(xssfRow);
                    if (!inquiryImportVo.getSuccess()){
                        return inquiryImportVo;
                    }
                    //把实体类中的数据放入到list集合中
                    planClassVoList.add(inquiryImportVo.getData());
                }

            }
        }
        ResultVo<List<PlanClassAddVo>> resultVo = readFile(file);
        if (!resultVo.getSuccess()){
            return resultVo;
        }
        List<PlanClassAddVo> planClassAddVoList = resultVo.getData();

        ResultVo validate = validate(planClassVoList);
        if (!validate.getSuccess()){
            return validate;
        }
//        5.验证不为空字段是否为空

//        6.验证字符长度是否符合需求

//        7.验证数据是否存在也就是是否合法
//        8.验证数据是否重复
//        9.对于需要转换的数据进行数据转换，比如数据库存的数据为数字格式，用户输入的为汉字，需要把汉字转换为数字存储
        //10.验证状态输入的是否是启用禁用。
        //批量入库
        ResultVo addPlanClass = addPlanClass(planClassVoList);
        if (!addPlanClass.getSuccess()){
            return addPlanClass;
        }

        return ResultBuilderVo.success();
    }

    public ResultVo validatee(List<PlanClassAddVo> planClassAddVoList) {
        //        5.验证不为空字段是否为空

//        6.验证字符长度是否符合需求

//        7.验证数据是否存在也就是是否合法
//        8.验证数据是否重复
        List<String> codeList = new ArrayList<>();

//        9.对于需要转换的数据进行数据转换，比如数据库存的数据为数字格式，用户输入的为汉字，需要把汉字转换为数字存储
        //10.验证状态输入的是否是启用禁用。
        for (PlanClassAddVo planClassAddVo:planClassAddVoList
                ) {
            if (StringUtils.isEmpty(planClassAddVo.getCode())) {
                return ResultBuilderVo.error("编码不能为空！");
            } else {
                if (planClassAddVo.getCode().length() > 30) {
                    return ResultBuilderVo.error("编码长度不能大于30个字节!");
                }
            }

            if (StringUtils.isEmpty(planClassAddVo.getName())) {
                return ResultBuilderVo.error("名称不能为空！");
            } else {
                if (planClassAddVo.getName().length() > 30) {
                    return ResultBuilderVo.error("名称长度不能大于30个字节!");
                }
            }


            if (StatusEnum.getValue(planClassAddVo.getStatusName())==null) {
                return ResultBuilderVo.error("状态只能填写启用或者禁用!");
            } else {
                Integer status = StatusEnum.getValue(planClassAddVo.getStatusName()
                );
                Boolean booleanStatus = status == 1 ? true : false;
                planClassAddVo.setStatus(booleanStatus);

            }
            codeList.add(planClassAddVo.getCode());

        }
        Set<String> setCode = new HashSet<>(codeList);
        if (setCode.size() != codeList.size()){
            return ResultBuilderVo.error("编码重复");
        }
        return ResultBuilderVo.success(planClassAddVoList);
    }


    public  ResultVo readFile(MultipartFile file)throws Exception {
        // 3.模板是否是需要导入的模板，验证模板是否正确
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取单元格中的信息 at0是获取sheet1中的数据。
        XSSFSheet sheet = workbook.getSheetAt(0);
        System.out.println(sheet.getRow(sheet.getFirstRowNum()).getCell(0));
        //验证第一列第一行的表格标头信息是否为 “询价单导入”，如果不是，提示模板错误。
        if (!String.valueOf(sheet.getRow(sheet.getFirstRowNum()).getCell(0)).equals("计划大类导入模板")) {
            return ResultBuilderVo.error("模板错误，请检查模板！");
        }
        List<PlanClassAddVo> planClassVoList = new ArrayList<>();
        //遍历excel表格中的所有数据，从第五行开始读取，没有数据时终止遍历。
        for (int i = sheet.getFirstRowNum() + 6; i <= sheet.getLastRowNum(); i++) {
            //读取每一行的数据
            XSSFRow xssfRow = sheet.getRow(i);
            if (xssfRow != null) {

                String test1 = String.valueOf(xssfRow.getCell(1)).trim();
                String test2 = String.valueOf(xssfRow.getCell(2)).trim();
                String test3 = String.valueOf(xssfRow.getCell(3)).trim();
                if (!test1.equals("") && !test1.equals("null")
                        || !test2.equals("") && !test2.equals("null")
                        || !test3.equals("") && !test3.equals("null")) {
                    //把每一行的数据放入到实体类中
                    ResultVo<PlanClassAddVo> inquiryImportVo = build(xssfRow);
                    if (!inquiryImportVo.getSuccess()) {
                        return inquiryImportVo;
                    }
                    //把实体类中的数据放入到list集合中
                    planClassVoList.add(inquiryImportVo.getData());
                }

            }
        }
        return ResultBuilderVo.success(planClassVoList);
    }

    public ResultVo build1(XSSFRow xssfRow){
        PlanClassAddVo planClassAddVo = new PlanClassAddVo();
        //        4.格式问题，必须保持统一格式，统一为字符串格式导入
        try {
            planClassAddVo.setCode(String.valueOf(xssfRow.getCell(1)));
        }catch (Exception e){
            return ResultBuilderVo.error("请检查编码格式是否为字符串格式");
        }

        planClassAddVo.setName(String.valueOf(xssfRow.getCell(2)));
        planClassAddVo.setCode(String.valueOf(xssfRow.getCell(3)));
        planClassAddVo.setRemark(String.valueOf(xssfRow.getCell(4)));
        return ResultBuilderVo.success(planClassAddVo);


    }

    public ResultVo yanzheng1(String name){
        //根据前端传过来的名称查询数据库，查看是否存在数据！
        int nameCount =  planClassMapper.queryByName(name);
        if (nameCount>0){
            return ResultBuilderVo.error(ErrorMessageClass.PLANLASSSADD);
        }

        return ResultBuilderVo.success();
    }



    /*导出*/
 /*   @Override
    public ResultVo export(HttpServletResponse response, String code, String name, Integer status)throws Exception {
//        检查需求，是否需要按照条件导出数据，如果有条件，根据条件查询数据，把数据插入到excel表格中，导出数据即可。如果没有条件，注意：要设置默认导出条数，当数据过多时设置默认导出10000条。
//        3.转换数据，把表中存在的数字转化为相应的汉字。

        //把数据查出来
        PlanClassSelectVo planClassSelectVo = new PlanClassSelectVo();
        planClassSelectVo.setCode(code);
        planClassSelectVo.setName(name);
        planClassSelectVo.setStatus(status);
        List<PlanClassVo> planClassVoList =  planClassMapper.queryExport(planClassSelectVo);
        //验证条数
        if (planClassVoList.size()>10000){
            return ResultBuilderVo.error("最多只能导出10000条数据！");
        }
        //数据转换
        for (PlanClassVo planClassVo:planClassVoList){
            Integer status2 = planClassVo.getStatus()==true?1:0;
            planClassVo.setStatusName(StatusEnum.getName(status2));
        }
        //把数据写入excel表格中
        //输出到浏览器

        //获取响应输出流
        ServletOutputStream out = response.getOutputStream();
        //给输出文件设置名称
        POIClass.toPackageOs(response, "计划大类导出");
        //读取模板中的数据
        InputStream in = Exception.toPackageIn("templates/计划大类导出模板.xlsx");
        //根据模板的数据、把查询出来的数据给摸版SHeet1组中的数据赋值、把excel输出到浏览器上
        writeDataToExcel(in, "Sheet1", planClassVoList, out);
        if (in != null) {
            in.close();
            out.close();
        }
        return ResultBuilderVo.success();
    }
*/
    // 由于此方法不能通用, 所以单独写在这里
  /*  private void writeDataToExcel(InputStream in, String sheetName,
                                  List<PlanClassVo> resultList, ServletOutputStream out) throws Exception {
        //POi读取模板
        XSSFWorkbook wb = new XSSFWorkbook(in);
        //读取sheet1中的数据
        Sheet sheet = wb.getSheet(sheetName);
        if (sheet != null) {
            //向sheet1中赋值，设置样式
            toResultListValueInfo(sheet, resultList);
        }
        //把数据写入到输出流中
        wb.write(out);
        //关闭poi方法
        wb.close();
    }
*/
    /**
     * 插入excel表中项目信息
     *
     * @param sheet
     */
   /* private void toResultListValueInfo(Sheet sheet, List<PlanClassVo> plantList) {
        //从第4行开始赋值
        int row_column = 5;
        //遍历数据集合
        for (PlanClassVo obj : plantList) {
            //创建一行的方法
            Row row = sheet.createRow(row_column);
            // 给第一列序号赋值赋值
            POIClass.toCellValue(row,0, obj.getId() + "");
            // 给第二列编码赋值
            POIClass.toCellValue(row, 1, obj.getCode() + "");
            // 给第3列名称赋值
            POIClass.toCellValue(row, 2, obj.getName() + "");
            // 给状态赋值
            POIClass.toCellValue(row, 3, obj.getStatusName() + "");
        *//*    //给描述赋值
            POIClass.toCellValue(row, 4, obj.getRemark() + "");*//*
            row_column++;
        }
    }

*/
    public ResultVo validate(List<PlanClassAddVo> planClassVoList){
        // 5.验证不为空字段是否为空
        // 6.验证字符长度是否符合需求
        // 9.对于需要转换的数据进行数据转换，比如数据库存的数据为数字格式，用户输入的为汉字，需要             把汉字转换为数字存储
        //10.验证状态输入的是否是启用禁用。
        // 8.验证数据是否重复


        List<String> codeList = new ArrayList<>();
        for (PlanClassAddVo planClassAddVo:planClassVoList){
            if (StringUtils.isEmpty(planClassAddVo.getCode())){
                return ResultBuilderVo.error("编码不能为空！");
            }else{
                if (planClassAddVo.getCode().length()>30){
                    return ResultBuilderVo.error("编码长度不能大于30个字节！");
                }
            }
            if (StringUtils.isEmpty(planClassAddVo.getName())){
                return ResultBuilderVo.error("名称不能为空！");
            }else{
                if (planClassAddVo.getName().length()>30){
                    return ResultBuilderVo.error("名称长度不能大于30个字节！");
                }
            }
            if (StatusEnum.getValue(planClassAddVo.getStatusName())==null){
                return ResultBuilderVo.error("状态只能填写启用或者禁用！");
            }else {
                Integer status = StatusEnum.getValue(planClassAddVo.getStatusName());
                Boolean booleanStatus = status == 1?true:false;
                planClassAddVo.setStatus(booleanStatus);
            }
            codeList.add(planClassAddVo.getCode());
        }
        Set<String> setCode = new HashSet<>(codeList);
        if (setCode.size()!=codeList.size()){
            return ResultBuilderVo.error("编码重复！");
        }
        return ResultBuilderVo.success();
    }

    public ResultVo readFilee(MultipartFile file)throws Exception{
        //        3.模板是否是需要导入的模板，验证模板是否正确
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取单元格中的信息 at0是获取sheet1中的数据。
        XSSFSheet sheet = workbook.getSheetAt(0);
        System.out.println(sheet.getRow(sheet.getFirstRowNum()).getCell(0));
        //验证第一列第一行的表格标头信息是否为 “询价单导入”，如果不是，提示模板错误。
        if (!String.valueOf(sheet.getRow(sheet.getFirstRowNum()).getCell(0)).equals("计划大类导入模板")) {
            return ResultBuilderVo.error("模板错误，请检查模板！");
        }
        List<PlanClassAddVo> planClassVoList = new ArrayList<>();
        //遍历excel表格中的所有数据，从第五行开始读取，没有数据时终止遍历。
        for (int i = sheet.getFirstRowNum() + 4; i <= sheet.getLastRowNum(); i++) {
            //读取每一行的数据
            XSSFRow xssfRow = sheet.getRow(i);
            if(xssfRow!=null) {
                String test1 = String.valueOf(xssfRow.getCell(1)).trim();
                String test2 = String.valueOf(xssfRow.getCell(2)).trim();
                String test3 = String.valueOf(xssfRow.getCell(3)).trim();
                if (!test1.equals("")&&!test1.equals("null")
                        ||!test2.equals("")&&!test2.equals("null")
                        ||!test3.equals("")&&!test3.equals("null")){
                    //把每一行的数据放入到实体类中
                    ResultVo<PlanClassAddVo> inquiryImportVo = build(xssfRow);
                    if (!inquiryImportVo.getSuccess()){
                        return inquiryImportVo;
                    }
                    //把实体类中的数据放入到list集合中
                    planClassVoList.add(inquiryImportVo.getData());
                }

            }
        }
        return ResultBuilderVo.success(planClassVoList);
    }



    public ResultVo build(XSSFRow xssfRow){
        PlanClassAddVo planClassAddVo = new PlanClassAddVo();
        //        4.格式问题，必须保持统一格式，统一为字符串格式导入
        try {
            planClassAddVo.setCode(String.valueOf(xssfRow.getCell(1)));
        }catch (Exception e){
            return ResultBuilderVo.error("请检查编码格式是否为字符串格式");
        }

        planClassAddVo.setName(String.valueOf(xssfRow.getCell(2)));
        planClassAddVo.setStatusName(String.valueOf(xssfRow.getCell(3)));
        planClassAddVo.setRemark(String.valueOf(xssfRow.getCell(4)));
        return ResultBuilderVo.success(planClassAddVo);
    }

    public ResultVo yanzheng(String name){
        //根据前端传过来的名称查询数据库，查看是否存在数据！
        int nameCount =  planClassMapper.queryByName(name);
        if (nameCount>0){
            return ResultBuilderVo.error(ErrorMessageClass.PLANLASSSADD);
        }

        return ResultBuilderVo.success();
    }
}
